/**
 * Facebook Javascript Emulation
 * Copyright (C) 2010 Nicholas Almeida
 * -----------------------------------
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 * -----------------------------------
 * 
 * Emulates all Facebook methods and functions for DOM elements.
 * Original function by "jussir" from: http://forum.developers.facebook.net/viewtopic.php?id=72498
 * Complete usage guide avaliable at: http://developers.facebook.com/docs/fbjs
 * 
 * @author Nicholas Almeida
 * @since 10/16/2010
 * @version 1.1.4
 */
var FBJSEmulator = function() {
	
	var VERSION = '1.1.4';
	
	this.getParentNode = function()	 {
		if (this.parentNode === null) {
			return false;
		}
		return this.parentNode;
	};
	this.getNodeType = function() { return this.nodeType; };
	this.getNextSibling = function() { return this.nextSibling; };
	this.getPreviousSibling = function() { return this.previousSibling; };
	this.getId = function() { return this.id; };
	this.getFirstChild = function(newId) { return this.firstChild; };
	this.getLastChild = function(newId) { return this.lastChild; };
	this.getChildNodes = function() {
		// return child nodes as array, except skip text node:
		var nodeList = this.childNodes;
		var children = [];
		for (var i = 0; i < nodeList.length; i++) {
			if (nodeList[i].toString() != '[object Text]') {
				children.push(nodeList[i]);
			}
		}
		return children;
	};
	this.getAction = function() { return this.action; };
	this.getValue = function() { return this.value; };
	this.getSrc = function() { return this.src; };
	this.getClassName = function() { return this.className; };
	this.getTagName = function() { return this.tagName; };
	this.getDir = function() { return this.dir; };
	this.getChecked = function() { return this.checked; };
	this.getClientWidth = function() { return this.clientWidth; };
	this.getClientHeight = function() { return this.clientHeight; };
	this.getOffsetWidth = function() { return this.offsetWidth; };
	this.getOffsetHeight = function() { return this.offsetHeight; };
	this.getHref = function() { return this.href; };
	this.getTarget = function() { return this.target; };
	
	// @see: http://blog.stchur.com/2006/06/21/css-computed-style/
	this.getStyle = function(p_str) { 
		var computedStyle;
		if (typeof this.currentStyle != 'undefined') { 
			computedStyle = this.currentStyle; 
		} else { 
			computedStyle = document.defaultView.getComputedStyle(this, null); 
		}
		return computedStyle[p_str];
	};
	
	//@see: http://vishalsays.wordpress.com/2007/12/21/finding-elements-top-and-left-using-javascript/
	this._getTopLeft = function(elm) {
		var x, y = 0;
			x = elm.offsetLeft;
			y = elm.offsetTop;
		elm = elm.offsetParent;
		while(elm !== null) {
			x = parseInt(x, 10) + parseInt(elm.offsetLeft, 10);
			y = parseInt(y, 10) + parseInt(elm.offsetTop, 10);
			elm = elm.offsetParent;
		}
		return {top:y, left: x};
	};
	
	this.getAbsoluteTop = function() { return this._getTopLeft(this).top; };
	this.getAbsoluteLeft = function() { return this._getTopLeft(this).left; };
	this.getScrollTop = function() { return this.scrollTop; };
	this.getScrollLeft = function() { return this.scrollLeft; };
	this.getScrollHeight = function() { return this.scrollHeight; };
	this.getScrollWidth = function() { return this.scrollWidth; };
	this.getTabIndex = function() { return this.tabIndex; };
	this.getTitle = function() { return this.title; };
	this.getName = function() { return this.name; };
	this.getCols = function() { return this.cols; };
	this.getRows = function() { return this.rows; };
	this.getAccessKey = function() { return this.accesKey; };
	this.getDisabled = function() { return this.disabled; };
	this.getReadOnly = function() { return this.readOnly; };
	this.getType = function() { return this.type; };
	this.getSelectedIndex = function() { return this.selectedIndex; };
	this.getSelected = function() { return this.selected; };

	this.setId = function(newId) { this.id = newId; return this; };
	this.setInnerFBML = function(new_fbml) { this.innerHTML = new_fbml; return this; };
	this.setInnerXHTML = function(str) { this.innerHTML = str; return this; };
	this.setTextValue = function(str) { this.innerHTML = str; return this; };
	this.setAction = function(act) { this.action = act; return this; };
	this.setValue = function(str) { this.value = str; return this; };
	this.setHref = function(str) { this.href = str; return this; };
	this.setTarget = function(str) { this.target = str; return this; };
	this.setSrc = function(str) { this.src = str; return this; };
	this.setClassName = function(str) { this.className = str; return this; };
	this.setDir = function(str) { this.dir = str; return this; };
	this.setChecked = function(str) { this.checked = str; return this; };
	this.setStyle = function(key, value) { 
		if(arguments.length <= 1) {
			if(Object.prototype.toString.call(key) === '[object Object]') {
				for(var a in key) {
					if(key.hasOwnProperty(a)){
						this.style[a] = key[a];
					}
				}
			}
		} else {
			this.style[key] = value;
		}
		return this; 
	};
	this.setScrollTop = function(str) { this.scrollTop = str; return this; };
	this.setScrollLeft = function(str) { this.scrollLeft = str; return this; };
	this.setTabIndex = function(str) { this.tabIndex = str; return this; };
	this.setTitle = function(str) { this.title = str; return this; };
	this.setName = function(str) { this.name = str; return this; };
	this.setCols = function(str) { this.cols = str; return this; };
	this.setRows = function(str) { this.rows = str; return this; };
	this.setAccessKey = function(str) { this.accesKey = str; return this; };
	this.setDisabled = function(str) { this.disabled = str; return this; };
	this.setReadOnly = function(str) { this.readOnly = str; return this; };
	this.setType = function(str) { this.type = str; return this; };
	this.setSelectedIndex = function(str) { this.selectedIndex = str; return this; };
	this.setSelected = function(str) { this.selected = str; return this; };

	this.addClassName = function(str) { this.className = this.className + ' ' + str; return this; };
	this.hasClassName = function(str) {
		if (typeof this.className == 'undefined') {
			return false;
		}
		var found = false;
		var _arr = this.className.split(' ');
		for(var i=0; i<_arr.length;i++){
			if (_arr[i] == str) {
				found = true;
			}
		}

		return found;
	};
	this.removeClassName = function(remove_name) {
		if (!this.className) {
			return;
		}
		var newClassAttr = '';

		var _arr = this.className.split(' ');
		for(var i=0; i<_arr.length;i++){
			if (_arr[i] != remove_name) {
				newClassAttr += (_arr[i] + ' ');
			}
		}
		this.className = newClassAttr;
	};
	
	this.cloneNode = (function(old_clone){
		return function(bool){
			var clone;
			try{ clone = old_clone.call(this, true); }
			catch(e){ clone = old_clone(this); };
			initFBJSEmulator(clone);
			return clone;
		}
	})(this.cloneNode);

	this.getRootElement = function() { return document.getElementById('root'); };
	this.setLocation = function(str) { /*global window */window.location = str; };
};
var Ajax = function() {
	/*global ActiveXObject*/
	try{
	    this.xmlhttp = new XMLHttpRequest();
	}catch(ee){
		try{
			this.xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
		}catch(eee){
			try{
				this.xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
			}catch(E){
				this.xmlhttp = false;
			}
		}
	}
	var _this = this;
	this._parseResponse = function(p_results) {
		var _result = p_results;
		var _response = null;
		switch (_this.responseType) {
			case Ajax.JSON :
				/*jslint evil: true */
				_response = (new Function('return ' + _result))();
				break;
			case Ajax.FBML :
			case Ajax.RAW :
				_response = _result;
				break;
		}
		_this.ondone(_response);
	};
	this.serializeObj = function(p_query) {
		var a, _query = '';
		for(a in p_query){
			if(p_query.hasOwnProperty(a)) {
				_query += a + '=' + p_query[a].toString() + '&';
			}
		}
		return _query;
	};
	
	// FB Methods
	this.ondone = function(p_data){};
	this.onerror = function(){};
	this.requireLogin = false;
	this.responseType = Ajax.RAW;
	this.useLocalProxy = false;
	this.abort = function(){};
	this.post = function(p_url, p_query) {
		try{
		    _this.xmlhttp.onreadystatechange = function(){
				if(_this.xmlhttp.readyState == 4 ){
					if(!_this.xmlhttp.responseText){
						return false;
					}
					_this._parseResponse(_this.xmlhttp.responseText);
				}
			};
			
			// transforming query inline!
			var _query = _this.serializeObj(p_query);
			
			_this.xmlhttp.open('POST', p_url, true);
			_this.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
		    _this.xmlhttp.send(_query);
		} catch (err){
			_this.onerror();
			return false;
		}
	};

};
Ajax.RAW = 'raw';
Ajax.JSON = 'json';
Ajax.FBML = 'fbml';

document.getRootElement = function() { return document.getElementById('root'); };
document.setLocation = function(str) { /*global window */window.location = str; };

document.createElement = (function (fn){
    return function (type, id, className)
    {
        var elem = fn.call(document, type);
        if (id) elem.id = id;
        if (className) elem.className = className;
        FBJSEmulator.apply(elem);
        return elem;
    };
})(document.createElement);


var initFBJSEmulator = function(_root){
	if(!_root) {
		throw new Error('FBJS Error: Unable to find DOM element id:"root".');
	}
	var _rootChildren = _root.getElementsByTagName('*');
	FBJSEmulator.apply(_root);
	var i = _rootChildren.length-1;
	while(i>=0) {
		FBJSEmulator.apply(_rootChildren[i]);
		i--;
	}
};
initFBJSEmulator(document.getElementById('root'));